﻿using Abp;
using Abp.Domain.Repositories;
using Abp.Extensions;
using Abp.UI;
using Mt.Site.Core.WorkFlows.Design.Entities;
using Mt.Site.Core.WorkFlows.Process.Entities;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;

namespace Mt.Site.Core.WorkFlows.Design
{
    public class WorkflowDesignService:MtSiteDomainServiceBase,IWorkflowDesignService
    {
        private readonly IRepository<WorkFlowCategeory, Guid> _workFlowCategeoryRepository;
        private readonly IRepository<WorkFlow, Guid> _workFlowRepository;
        private readonly IRepository<WorkFlowForm, Guid> _workFlowFormRepository;
        private readonly IRepository<WorkFlowNode, Guid> _workFlowNodeRepository;
        private readonly IRepository<WorkFlowPaper, Guid> _workFlowPaperRepository;
        private readonly IRepository<WorkFlowPaperArchive, Guid> _workFlowPaperArchiveRepository;

        public WorkflowDesignService(
            IRepository<WorkFlowCategeory, Guid> workFlowCategeoryRepository,
            IRepository<WorkFlow, Guid> workFlowRepository,
            IRepository<WorkFlowForm, Guid> workFlowFormRepository,
            IRepository<WorkFlowNode, Guid> workFlowNodeRepository,
            IRepository<WorkFlowPaper, Guid> workFlowPaperRepository,
            IRepository<WorkFlowPaperArchive, Guid> workFlowPaperArchiveRepository)
        {
            _workFlowCategeoryRepository = workFlowCategeoryRepository;
            _workFlowRepository = workFlowRepository;
            _workFlowFormRepository = workFlowFormRepository;
            _workFlowNodeRepository = workFlowNodeRepository;

            _workFlowPaperRepository = workFlowPaperRepository;
            _workFlowPaperArchiveRepository = workFlowPaperArchiveRepository;
        }

        #region 流程分类

        public async Task CreateCategoryAsync(WorkFlowCategeory entity)
        {
            await _workFlowCategeoryRepository.InsertAsync(entity);
        }
        public async Task UpdateCategoryAsync(WorkFlowCategeory entity)
        {
            await _workFlowCategeoryRepository.UpdateAsync(entity);
        }
        public async Task DeleteCategoryAsync(Guid id)
        {
            if (await _workFlowRepository.CountAsync(c => c.CategeoryId == id) == 0)
            {
                await _workFlowCategeoryRepository.DeleteAsync(id);
            }
            else
            {
                throw new UserFriendlyException("该分类下有流程定义，不能删除！");
            }
        }

        #endregion

        #region 流程
        public async Task CreateDesignAsync(WorkFlow entity)
        {
            await _workFlowRepository.InsertAsync(entity);

        }
        public async Task UpdateDesignAsync(WorkFlow entity)
        {
            await _workFlowRepository.UpdateAsync(entity);
        }
        public async Task DeleteDesignAsync(Guid id)
        {
            if (await IsHasPapers(id))
            {
                throw new UserFriendlyException("该流程已有稿件在流转，不能删除（删除流程定义前需删除该流程的所有在办、办结、归档的稿件）！");
            }
            else
            {
                await _workFlowFormRepository.DeleteAsync(c => c.WorkFlowId == id);
                await _workFlowNodeRepository.DeleteAsync(c => c.WorkflowId == id);
                await _workFlowRepository.DeleteAsync(id);
            }
        }

        public async Task<bool> IsHasPapers(Guid workFlowId)
        {
            var a = await CheckPapersCountAsync(workFlowId);
            return a > 0;
        }
        public async Task<int> CheckPapersCountAsync(Guid workFlowId)
        {
            var a = await _workFlowPaperRepository.CountAsync(c => c.WorkFlowId == workFlowId);
            var b = await _workFlowPaperArchiveRepository.CountAsync(c => c.WorkFlowId == workFlowId);

            return a + b;
        }

        public async Task CopyWorkFlowDefinitionAsync(Guid workFlowId)
        {
            var workFlow = await _workFlowRepository.GetAsync(workFlowId);
            var newWorkFlow = new WorkFlow
            {
                TenantId = workFlow.TenantId,
                IsActive = false,
                Order = workFlow.Order,
                Name = workFlow.Name + "（复制）",
                ShortName = workFlow.ShortName,
                CategeoryId = workFlow.CategeoryId,
                IsHaveAttachment = workFlow.IsHaveAttachment,
                IsHaveOnlineWord = workFlow.IsHaveOnlineWord,
                EntrustType = workFlow.EntrustType,
                Description = workFlow.Description,
                NumberFormat = workFlow.NumberFormat,
                DigitNumber = workFlow.DigitNumber,
                NumberCounting = workFlow.NumberCounting,
                UnitIdList = workFlow.UnitIdList,
                ShouldLogWhenDrawback = workFlow.ShouldLogWhenDrawback,
                OptionFunction = workFlow.OptionFunction  ,
                Id = Guid.NewGuid()
            };

            var nodeList = await _workFlowNodeRepository.GetAllListAsync(c => c.WorkflowId == workFlowId && c.IsActive);
            var nodeIdPairList = new List<NameValue>();
            var newNodeList = new List<WorkFlowNode>();

            foreach (var item in nodeList)
            {
                var newNode = new WorkFlowNode
                {
                    Id = Guid.NewGuid(),
                    TenantId = item.TenantId,
                    WorkflowId = newWorkFlow.Id,
                    IsActive = item.IsActive,
                    Order = item.Order,
                    Name = item.Name,
                    ShortName = item.ShortName,
                    Description = item.Description,
                    ActionScheme = item.ActionScheme,
                    UserIdList = item.UserIdList,
                    ActionList = item.ActionList,
                    CanEditAttachment = item.CanEditAttachment,
                    BeforeSelectFilter = item.BeforeSelectFilter,
                    BeforeSelectMoreFilter = item.BeforeSelectMoreFilter,
                    SelectedFilter = item.SelectedFilter,
                    SelectedMoreFilter = item.SelectedMoreFilter,
                    HandlingTimeLimit = item.HandlingTimeLimit,
                    IsAutoSendToNext = item.IsAutoSendToNext,
                    OptionFunction = item.OptionFunction,
                    NextNodeList = item.NextNodeList,
                    BackNodeList = item.BackNodeList
                };
                newNodeList.Add(newNode);
                nodeIdPairList.Add(new NameValue(item.Id.ToString().ToLower(), newNode.Id.ToString().ToLower()));
            }

            await _workFlowRepository.InsertAsync(newWorkFlow);
            foreach (var item in newNodeList)
            {
                item.NextNodeList = ReplaceNodeId(item.NextNodeList, nodeIdPairList);
                item.BackNodeList = ReplaceNodeId(item.BackNodeList, nodeIdPairList);
                await _workFlowNodeRepository.InsertAsync(item);
            }

            var formEntity = await _workFlowFormRepository.FirstOrDefaultAsync(c => c.WorkFlowId == workFlowId && c.IsActive);
            if (formEntity != null)
            {
                var newFormEntity = new WorkFlowForm
                {
                    WorkFlowId = newWorkFlow.Id,
                    HtmlData = ReplaceNodeId(formEntity.HtmlData, nodeIdPairList),
                    ExtensionData = ReplaceNodeId(formEntity.ExtensionData, nodeIdPairList),
                    IsActive = formEntity.IsActive
                };
                await _workFlowFormRepository.InsertAsync(newFormEntity);
            }
        }

        private string ReplaceNodeId(string obj, List<NameValue> nodeIdPairList)
        {
            if (obj.IsNullOrEmpty())
            {
                return "";
            }


            foreach (var item in nodeIdPairList)
            {

                obj = obj.Replace(item.Name, item.Value);
            }

            return obj;
        }
        #endregion

        #region 流程表单
        public async Task CreateWorkFlowFormAsync(WorkFlowForm entity)
        {
            await _workFlowFormRepository.InsertAsync(entity);
        }

        public async Task UpdateWorkFlowFormAsync(WorkFlowForm entity)
        {
            await _workFlowFormRepository.UpdateAsync(entity);
        }

        public async Task DeleteWorkFlowFormAsync(Guid id)
        {
            await _workFlowFormRepository.DeleteAsync(id);
        }
        #endregion


        #region 流程步骤
        public async Task CreateWorkFlowNodeAsync(WorkFlowNode entity)
        {
            await _workFlowNodeRepository.InsertAsync(entity);
        }

        public async Task UpdateWorkFlowNodeAsync(WorkFlowNode entity)
        {
            await _workFlowNodeRepository.UpdateAsync(entity);
        }

        //该流程已有稿件在流转或当前节点是第一步起始步骤，不能删除（删除流程定义前需删除该流程的所有在办、办结、归档的稿件）！
        public async Task<bool> CanNodeBeRemoveOrEdit(WorkFlowNode node, List<WorkFlowNode> allBrotherNodes)
        {
            if (node != null)
            {
                if (await IsHasPapers(node.WorkflowId))
                {
                    //起始步骤不能删
                    if(node.Id == allBrotherNodes.FirstOrDefault()?.Id)
                    {
                        return false;
                    }

                    //被使用了的不能删
                    var nodeId = node.Id.ToString().ToLower();
                    foreach (var item in allBrotherNodes)
                    {
                        if(item.NextNodeList != null && item.NextNodeList.IndexOf(nodeId, StringComparison.OrdinalIgnoreCase) >= 0)
                        {
                            return false;
                        }
                        if (item.BackNodeList != null && item.BackNodeList.IndexOf(nodeId, StringComparison.OrdinalIgnoreCase) >= 0)
                        {
                            return false;
                        }
                    }

                    return true;
                }
                else
                {
                    return true;
                }
            }
            return true;
        }
        #endregion
    }
}
